package com.woniuxy.microgoldservice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.woniuxy.bean.BillBean;
import com.woniuxy.bean.ResultBean;
import com.woniuxy.bean.regularbean.MemberAccountInnerBean;
import com.woniuxy.bean.regularbean.MemberAccountOutBean;
import com.woniuxy.microgoldservice.bean.*;
import com.woniuxy.microgoldservice.feign.UserAccountFeign;
import com.woniuxy.microgoldservice.mapper.GoldAccumulateMapper;
import com.woniuxy.microgoldservice.mapper.GoldPriceMapper;
import com.woniuxy.microgoldservice.mapper.GoldPurchaseMapper;
import com.woniuxy.microgoldservice.service.IGoldPurchaseService;
import com.woniuxy.microgoldservice.service.IGoldpriceService;
import com.woniuxy.microgoldservice.utils.CodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author hongbin
 * @date 2021-04-13 20:17
 * Description：黄金购买信息
 */
@Slf4j
@Service
public class GoldPurchaseServiceImpl implements IGoldPurchaseService {
    @Resource
    ValueOperations<String, Object> valueOperations;

    @Resource
    private IGoldpriceService goldpriceService;

    @Resource
    private GoldPriceMapper goldPriceMapper;

    @Resource
    private GoldAccumulateMapper accumulateMapper;

    @Resource
    private UserAccountFeign userAccountFeign;

    @Resource
    private GoldPurchaseMapper purchaseMapper;

    @Override
    public ResultBean getHoldGrammage(String userName) {
        BigDecimal holdGrammage = purchaseMapper.getHoldGrammage(userName);
        Long proId = goldPriceMapper.selectProId();
        GoldPriceInfo todayGoldPrice = goldPriceMapper.getTodayGoldPrice(proId);
        HashMap<String , Object> map = new HashMap<>();
        map.put("holdGrammage", holdGrammage);
        map.put("price",todayGoldPrice.getPrice());
        return ResultBean.builder().data(map).msg("OK").code(200).build();
    }

    /**
     * @Author: hongbin
     * @Description: 获取产品收益信息
     * @DateTime: 19:25 2021/4/15
     * @Params: [userName]
     * @Return java.lang.String
     */
    @Override
    public ResultBean getPurchase(String userName) {
        MemberAccountOutBean outBean = null;
        try {
            boolean empty = userName.isEmpty();
            if (empty) {
                return ResultBean.builder().code(805).msg("没有参数").build();
            }
            //查询购买的收益
            GoldPurchase purchase = purchaseMapper.getPurchase(userName);

            if (purchase == null) {
                return ResultBean.builder().
                        code(Integer.parseInt(CodeEnum.PURCHASE_ERROR.getCode())).
                        msg(CodeEnum.PURCHASE_ERROR.getMessage()).data(new GoldPurchase()).build();
            }

            //封装请求
            outBean = new MemberAccountOutBean();

            MemberAccountInnerBean innerBean = new MemberAccountInnerBean();
            //用户账号
            innerBean.setMemberAccount(userName);
            //购买的金额
            innerBean.setOverAllBalance(purchase.getMonetary().doubleValue());
            //总的收益
            innerBean.setTotalEarnings(purchase.getEarnings().doubleValue());
            Map<String, Object> map = null;
            try {
                map = goldpriceService.selectTodayPrice();
            } catch (Exception e) {
                e.printStackTrace();
                return ResultBean.builder().code(805).msg("OK").data(outBean).build();
            }
            Double price = (Double) map.get("price");
            //产品ID
            innerBean.setFixedDepositId(purchase.getProId().intValue());

            //昨日收益
            innerBean.setTodayEarnings(purchase.getYesterDayEarnings());

            ArrayList<MemberAccountInnerBean> list = new ArrayList<>();
            list.add(innerBean);
            //产品信息集合
            outBean.setMemberAccountInnerBeans(list);
            //产品总收益
            outBean.setSumEarnings(purchase.getEarnings().doubleValue());
            //总价值，购买花的钱
            outBean.setSumOverAllBalance(purchase.getMonetary().doubleValue());
            //昨日总收益
            outBean.setTodaySumEarnings(purchase.getYesterDayEarnings());
        } catch (NumberFormatException e) {
            e.printStackTrace();
            return ResultBean.builder().code(500).msg("没有数据").build();
        }

        return ResultBean.builder().code(200).msg("OK").data(outBean).build();
    }


    /**
     * @Author: hongbin
     * @Description: 购买黄金产品生成订单
     * @DateTime: 19:26 2021/4/15
     * @Params: [money, username, proId]
     * @Return java.lang.String
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBean buyGold(GoldOrderDTO goldOrderDTO) {


        try {
            //防止重复发送数据
            boolean lock = lock(goldOrderDTO.getUsername(), goldOrderDTO.getPwd());
            if (!lock) {
                return ResultBean.builder().code(809).msg("请勿重复点击").build();
            }

            //判断是密码是否正确

            GoldAccumulateInfo goldAccumulateInfo = accumulateMapper.selectProductInfo(goldOrderDTO.getProId());


            //判断余额是否充足 钱包密码是否正确
            BillBean billBean = new BillBean();
            billBean.setMemberName(goldOrderDTO.getUsername());
            billBean.setModifiedPrice(goldOrderDTO.getMoney());
            billBean.setProductId(goldOrderDTO.getProId().intValue());
            billBean.setProductType("黄金");
            billBean.setProductName(goldAccumulateInfo.getProductName());
            billBean.setPayPassword(goldOrderDTO.getPwd());
            billBean.setOrderType(CodeEnum.BUY_INFO.getMessage());
            billBean.setPayType(goldOrderDTO.getPayType());
            billBean.setCouponId(goldOrderDTO.getCouponId());
            billBean.setBankCardId(goldOrderDTO.getBankCardId());


            String s = userAccountFeign.balancePayment(billBean);
            JSONObject jsonObject = JSONObject.parseObject(s);
            if (jsonObject.getInteger("code") != 200) {
                unlock(goldOrderDTO.getUsername());
                return ResultBean.builder().data(s).msg("钱包异常").code(810).build();
            }

            //计算保存黄金克数
            Double nowGoldPrice = goldpriceService.getNowGoldPrice();

            BigDecimal grammage = new BigDecimal(goldOrderDTO.getMoney() / nowGoldPrice);

            //查询库存数
            Double amount = accumulateMapper.queryInventory(goldOrderDTO.getProId());
            if (grammage.divide(new BigDecimal(amount), 2, BigDecimal.ROUND_HALF_UP).doubleValue() < 0) {
                unlock(goldOrderDTO.getUsername());
                return ResultBean.builder().code(Integer.parseInt(CodeEnum.GOLD_BALANCE_ERROT.getCode())).msg(CodeEnum.GOLD_BALANCE_ERROT.getMessage()).build();
            }
            //减库存
            int i1 = accumulateMapper.inventoryReduction(goldOrderDTO.getProId(), grammage);

            //如果购买过就追加克数
            boolean b = purchaseMapper.selectExistsPurchase(goldOrderDTO.getUsername());
            if (b) {
                purchaseMapper.addPurchase(goldOrderDTO.getUsername(), goldOrderDTO.getMoney(), grammage);
            } else {
                //添加到黄金购买信息中
                purchaseMapper.savePurchase(grammage, goldOrderDTO.getMoney(), goldOrderDTO.getUsername(), goldOrderDTO.getProId());
            }
            purchaseMapper.addPurchaseOrder(goldOrderDTO.getProId(), goldOrderDTO.getUsername(), grammage, nowGoldPrice, goldOrderDTO.getMoney());

            unlock(goldOrderDTO.getUsername());
        } catch (Exception e) {
            e.printStackTrace();
            unlock(goldOrderDTO.getUsername());
            return ResultBean.builder().code(Integer.parseInt(CodeEnum.GOLD_BUY_ERROR.getCode())).msg(CodeEnum.GOLD_BUY_ERROR.getMessage()).build();
        }
        return ResultBean.builder().code(200).msg("OK").build();
    }

    /**
     * @Author: hongbin
     * @Description: 判断余额是否充足
     * @DateTime: 16:56 2021/4/19
     * @Params: [money, username, proId, pwd]
     * @Return java.lang.Boolean
     */
    private Boolean judgeBalance(Double money, String username, Long proId, String pwd, String payType, int bankCardId, String productName) {

        BillBean billBean = new BillBean();
        billBean.setMemberName(username);
        billBean.setModifiedPrice(money);
        billBean.setProductId(proId.intValue());
        billBean.setProductType("黄金");
        billBean.setProductName(productName);
        billBean.setPayPassword(pwd);
        billBean.setOrderType(CodeEnum.BUY_INFO.getMessage());
        billBean.setPayType(payType);
        billBean.setBankCardId(bankCardId);


        String s = userAccountFeign.balancePayment(billBean);
        JSONObject jsonObject = JSONObject.parseObject(s);
        Integer code = jsonObject.getInteger("code");
        if (code != 200) {
            return true;
        }
        return false;
    }


    /**
     * @Author: hongbin
     * @Description: 获取黄金总资产
     * @DateTime: 16:05 2021/4/20
     * @Params: [userName]
     * @Return java.lang.String
     */
    @Override
    public ResultBean getAsset(String userName) {

        AssetDAO asset = purchaseMapper.getAsset(userName);
        Long proId = accumulateMapper.selectProId();
        GoldAccumulateInfo goldAccumulateInfo = accumulateMapper.selectById(proId);


        //没有数据设置为默认值
        if (asset == null) {
            asset = new AssetDAO();
            asset.setTotal(0d);
            asset.setYesterday(0d);
            asset.setHold(0d);
            asset.setAccumulatedIncome(0d);
            asset.setSuccessfulPurchase("");
            asset.setParticularsRule(goldAccumulateInfo.getReceivePrice());
            asset.setSuccessfulPurchase("0");
            asset.setFlexibleAccount(0d);
            return ResultBean.builder().code(200).msg("OK").data(asset).build();
        }


        //产品名称
        asset.setProductName(goldAccumulateInfo.getProductName());
        //交易规则
        asset.setParticularsRule(goldAccumulateInfo.getReceivePrice());
        String date = asset.getEarningsDate().substring(0, 10);
        try {
            Date parse = new SimpleDateFormat("yyyy-MM-dd").parse(date);
            Calendar ins = Calendar.getInstance();
            ins.setTime(parse);
            ins.add(Calendar.DATE, 1);
            Date time = ins.getTime();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            String format = simpleDateFormat.format(time);
            //收益日期
            asset.setEarningsDate(format);
        } catch (ParseException e) {
            e.printStackTrace();
        }


        return ResultBean.builder().code(200).msg("OK").data(asset).build();

    }

    /**
     * @Author: hongbin
     * @Description: 赎回黄金
     * @DateTime: 19:27 2021/4/15
     * @Params: [username, grammage, proId]
     * @Return java.lang.String
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBean redemptionGold(GoldOrderDTO goldOrderDTO) {

        try {
            //防止重复发送数据
            String value = UUID.randomUUID().toString();
            if (!lock(goldOrderDTO.getUsername(), value)) {
                return ResultBean.builder().code(809).msg("请勿重复点击").build();
            }

            //赎回的克数是否为全部
            boolean flage = false;

            //判断黄金克数是否充足
            BigDecimal goldGrammage = purchaseMapper.queryInventory(goldOrderDTO.getUsername());
            BigDecimal getGrammage = new BigDecimal(goldOrderDTO.getGrammage()).setScale(4,BigDecimal.ROUND_HALF_DOWN);
            BigDecimal subtract = goldGrammage.subtract(getGrammage);

            if (subtract.doubleValue() < 0) {
                unlock(goldOrderDTO.getUsername());
                return ResultBean.builder().
                        code(Integer.parseInt(CodeEnum.GOLD_BALANCE_ERROT.getCode())).
                        msg(CodeEnum.GOLD_BALANCE_ERROT.getMessage()).build();
            }

            //获取当前时刻金价
            Double monetary = goldpriceService.getNowGoldPrice();
            BigDecimal redemptionMoney = null;
            //赎回的金额
            if (subtract.doubleValue() < 1) {
                flage = true;
                //不足一克，全部赎回
                redemptionMoney = new BigDecimal(monetary).multiply(goldGrammage);
            } else {
                redemptionMoney = new BigDecimal(monetary).multiply(new BigDecimal(goldOrderDTO.getGrammage()));
            }

            //平台扣除费率
            GoldAccumulateInfo rate = accumulateMapper.selectRate(goldOrderDTO.getProId());
            Double serverCharge = rate.getServerCharge();

            //平台收取的费用
            BigDecimal multiply = redemptionMoney.multiply(new BigDecimal(serverCharge / 100));

            int i1 = purchaseMapper.addEarnings(rate.getProductName(), multiply.doubleValue());

            //用户可获得的钱
            BigDecimal totalMoney = redemptionMoney.subtract(multiply);

            BillBean billBean = new BillBean();
            billBean.setMemberName(goldOrderDTO.getUsername());
            billBean.setModifiedPrice(-totalMoney.doubleValue());
            billBean.setProductId(goldOrderDTO.getProId().intValue());
            billBean.setPayPassword(goldOrderDTO.getPwd());
            billBean.setProductType(CodeEnum.PRODUCT_NAME.getMessage());
            billBean.setBankCardId(0);
            billBean.setPayType(goldOrderDTO.getPayType());
            billBean.setProductName(rate.getProductName());
            billBean.setOrderType(CodeEnum.REDEMPTION_INFOCODE_ENUM.getMessage());
            //赎回到钱包
            String s = userAccountFeign.balancePayment(billBean);
            JSONObject jsonObject = JSONObject.parseObject(s);
            Integer code = jsonObject.getInteger("code");
            //验证密码
            if (code != 200) {
                unlock(goldOrderDTO.getUsername());
                return ResultBean.builder().code(810).data(s).msg("钱包异常").build();
            }

            log.info(s);
            //购买克数的和
            BigDecimal redemptionGrammage = new BigDecimal(0);
            //剩余克数
            BigDecimal residueGrammage = new BigDecimal(0);

            ArrayList<Long> list = new ArrayList<>();

            Long flageId = 0L;

            //查询该用户购买的记录
            List<Map<String, Object>> maps = purchaseMapper.selectPurchaseOrderByUserName(goldOrderDTO.getUsername());
            for (Map<String, Object> map : maps) {

                redemptionGrammage =redemptionGrammage.add ((BigDecimal) map.get("grammage"));

                //当本次赎回克数小于等于购买累积克数时记录下id
                if (goldOrderDTO.getGrammage() <= redemptionGrammage.doubleValue()) {

                    flageId = (Long) map.get("id");
                    //累积克数减去本次赎回克数
                    residueGrammage = redemptionGrammage.subtract(new BigDecimal(goldOrderDTO.getGrammage()));
                    break;
                }
                list.add((Long) map.get("id"));
            }
            if (!flage) {
                if(list.size()>0){
                    //删除购买记录，不包含flageid
                    purchaseMapper.deleteOrder(list);
                }
                //删除赎回的多余的黄金克数
                purchaseMapper.updateResidueGrammage(flageId, residueGrammage);
                //没有全部赎回黄金
                purchaseMapper.redemptionGold(goldOrderDTO.getUsername(), goldOrderDTO.getGrammage(), redemptionMoney.doubleValue());
            } else {

                if(list.size()>0){
                    //删除购买记录，不包含flageid
                    purchaseMapper.deleteOrder(list);
                }
                //删除购买记录，包含flageid
                purchaseMapper.deleteToFlageId(flageId);
                //赎回全部
                purchaseMapper.redemptionGold(goldOrderDTO.getUsername(), goldGrammage.doubleValue(), redemptionMoney.doubleValue());
            }

            unlock(goldOrderDTO.getUsername());
        } catch (Exception e) {
            e.printStackTrace();
            unlock(goldOrderDTO.getUsername());
            return ResultBean.builder().code(Integer.parseInt(CodeEnum.GOLD_REDEEM_ERROR.getCode())).msg(CodeEnum.GOLD_REDEEM_ERROR.getMessage()).build();
        }
        return ResultBean.builder().code(200).msg("OK").data("ok").build();

    }

    /**
     * @Author: hongbin
     * @Description: 加锁
     * @DateTime: 17:02 2021/4/16
     * @Params: [key, value]
     * @Return boolean
     */
    public boolean lock(String key, String value) {
        if (key.isEmpty() || value.isEmpty()) {
            return false;
        }

        if (valueOperations.setIfAbsent(key, value)) {
            return true;
        }

        return false;
    }


    /**
     * 解锁
     *
     * @param key
     * @param
     */
    public void unlock(String key) {

        try {
            String currentValue = (String) valueOperations.get(key);

            if (!StringUtils.isEmpty(currentValue)) {

                valueOperations.getOperations().delete(key);

            }
        } catch (Exception e) {
            log.error("使用redis解锁发生异常:{}", e.getMessage());
        }


    }


}
